
#include "Dispatcher.h"
#include <sys/poll.h>
#include "Channel.h"
#define MAX 1024
struct PollData
{
    int maxfd;
    struct pollfd fds[MAX];
};

static void *pollinit(); // Dispacherdata

static int pollAdd(struct Channel *channel, struct EventLoop *eventLoop);

static int pollRemove(struct Channel *channel, struct EventLoop *eventLoop);

static int pollModify(struct Channel *channel, struct EventLoop *eventLoop);

static int pollDispatch(struct EventLoop *eventLoop, int timeout);

static int pollClear(struct EventLoop *eventLoop);

// 如何和Dispatcher关联
struct Dispatcher PollDispatcher = {
    pollinit,
    pollAdd,
    pollRemove,
    pollModify,
    pollDispatch,
    pollClear};

static void *pollinit()
{
    struct PollData *data = (struct PollData *)malloc(sizeof(struct PollData));
    data->maxfd = 0;

        //    struct pollfd {
        //        int   fd;         /* file descriptor */
        //        short events;     /* requested events */
        //        short revents;    /* returned events */
        //    };
    for (int i = 0; i < MAX; i++)
    {
        // 先把所有位置初始化为-1
        data->fds[i].fd = -1;
        data->fds[i].events = 0;
        data->fds[i].revents = 0;
    }
    return data;
}

/// @brief
/// @param channel  channel 的读或者写是我们自己定义的，跟linux的不一样
/// @param eventLoop
static int pollAdd(struct Channel *channel, struct EventLoop *eventLoop)
{
    struct PollData *data = (struct PollData *)eventLoop->DispatcherData;

    // 设置事件events
    int events = 0;
    if (channel->event & ReadEvent)
    {
        events |= POLLIN;
    }
    // 不能同时判断读或者写
    if (channel->event & WriteEvent)
    {
        events |= POLLOUT;
    }
    // 遍历找到一个空闲饿、位置放进去

    int i = 0;
    for (; i < MAX; i++)
    {
        if (data->fds[i].fd == -1)
        {
            // 说明找到一个空闲的位置
            data->fds[i].fd = channel->fd;
            data->fds[i].events = events;
            data->maxfd = (i > data->maxfd) ? i : data->maxfd;
            break;
        }
    }

    // 什么时候用poll elect 检测的fd不多 ，大多数是激活的 qq在聊天是激活  qq挂起不激活
    if (i >= MAX)
    {
        return -1;
    }
    // 添加到poll中

    return 0;
}

static int pollRemove(struct Channel *channel, struct EventLoop *eventLoop)
{
    struct PollData *data = (struct PollData *)eventLoop->DispatcherData;

    int i = 0;
    for (; i < MAX; i++)
    {
        if (data->fds[i].fd == channel->fd)
        {
            // 说明找到一个空闲的位置
            data->fds[i].fd = -1;
            data->fds[i].events = 0;
            data->fds[i].revents = 0;
            break;
        }
    }
    // 通过channel释放对应的TcpConnection 的资源
    channel->destoryCallBack(channel->arg);
    if (i >= MAX)
    {
        return -1;
    }

    // 什么时候用poll elect 检测的fd不多 ，大多数是激活的 qq在聊天是激活  qq挂起不激活

    return 0;
}

static int pollModify(struct Channel *channel, struct EventLoop *eventLoop)
{
    struct PollData *data = (struct PollData *)eventLoop->DispatcherData;

    // 设置事件events
    int events = 0;
    if (channel->event & ReadEvent)
    {
        events |= POLLIN;
    }
    // 不能同时判断读或者写
    if (channel->event & WriteEvent)
    {
        events |= POLLOUT;
    }
    // 遍历找到一个空闲饿、位置放进去

    int i = 0;
    for (; i < MAX; i++)
    {
        if (data->fds[i].fd == channel->fd)
        {
            // 说明找到一个空闲的位置
            data->fds[i].events = events;
            break;
        }
    }

    // 什么时候用poll elect 检测的fd不多 ，大多数是激活的 qq在聊天是激活  qq挂起不激活

    return 0;
}

// 我在想他这里为什什么要进行转换，说传过来的是void* 类型的
static int pollDispatch(struct EventLoop *eventLoop, int timeout)
{
    struct PollData *data = (struct PollData *)eventLoop->DispatcherData;

    int count = poll(data->fds, data->maxfd + 1, timeout * 1000); // 传进来的事件是ms

    if (count == -1)
    {
        perror("poll error");
    }

    // 这个count 只是表示多少个事件就绪了 ，并不能表示这写文件描述符是连续得
    for (int i = 0; i <= data->maxfd; i++)
    {
        // 判断返回来得事件是什么

        if (data->fds[i].fd == -1)
        {
            continue;
        }

        // if (data->fds[i].revents & POLLERR || data->fds[i].revents & POLLHUP)
        // {
        //     // 错误事件
        //     // 关闭文件描述符
        // }
        if (data->fds[i].revents & POLLIN)
        {
            // 读事件
            eventActivate(eventLoop, data->fds[i].fd, ReadEvent);
        }
        if (data->fds[i].revents & POLLOUT)
        {
            eventActivate(eventLoop, data->fds[i].fd, WriteEvent);
            // 写事件
        }
    }
    return 0;
}

static int pollClear(struct EventLoop *eventLoop)
{
    struct PollData *data = (struct PollData *)eventLoop->DispatcherData;
    // 创建的数组
    for (int i = 0; i < MAX; i++)
    {
        if (data->fds[i].fd != -1)
        {
            close(data->fds[i].fd);
            data->fds[i].fd = -1;
            data->fds[i].events = 0;
            data->fds[i].revents = 0;
        }
    }
    free(data);
    eventLoop->DispatcherData = NULL;
    free(data);
    return 0;
}
